#pragma once

#include "LoadingThread.h"

#include "sys/sysapi.h"

class ObjectModel;
class LoadingManager
{
public:
	LoadingManager(const String& cfgFileName,ObjectModel* system);
	virtual ~LoadingManager();

	bool LoadAllCategories();
	bool LoadCategory(const String& wsCategoryName);
	bool AsyncLoadCategory(const String& wsCategoryName);
	bool UnloadCategory(const String& wsCategoryName);

	void InitCategories();
	bool IsCategoryLoaded(const String& wsCategoryName) const
	{
		ComponentCategoryMap::const_iterator iter = m_mapComponentCategories.find(wsCategoryName);
		return (iter != m_mapComponentCategories.end()) && (iter->second.IsLoaded());
	}
	void GetComponentListInCategory(const String& wsCategoryName, StringArray& arrComponentList) const
	{
		ComponentCategoryMap::const_iterator iter = m_mapComponentCategories.find(wsCategoryName);
		if (iter != m_mapComponentCategories.end())
			arrComponentList = iter->second.GetComponents();
	}

	void LoadComponentDirectly(const String& wsComponentName);
	void NotifyLoaderThreadFinished(const String& wsCategoryName);

private:
	struct ComponentCategory
	{
	public:

		ComponentCategory()
			: m_wsCategoryName(L"")
			, m_bLoaded(false)
		{
		}

		ComponentCategory(const String& wsCategoryName)
			: m_wsCategoryName(wsCategoryName)
			, m_bLoaded(false)
		{
		}

		void SetLoadFlag(bool bSet)
		{
			m_bLoaded = bSet;
		}

		bool IsLoaded() const
		{
			return m_bLoaded;
		}

		const String& GetName() const
		{
			return m_wsCategoryName;
		}

		const StringArray& GetComponents() const
		{
			return m_arrComponents;
		}

		unsigned GetCount() const
		{
			return m_arrComponents.size();
		}

		void AddOneComponent(const String& wsComponentName)
		{
			m_arrComponents.push_back(wsComponentName);
		}

	private:
		String m_wsCategoryName;
		bool m_bLoaded;
		StringArray m_arrComponents;
	};


	//////////////////////////////////////////////////////////////////////////
	// typedefs
	typedef std::map<String, ComponentCategory> ComponentCategoryMap;
	typedef std::map<String, class LoadingThread*> ComponentLoaderThreadPool;
	typedef std::pair<String, uint32> KeyValuePair;
	typedef std::vector<KeyValuePair> KeyValuePairArray;

	//////////////////////////////////////////////////////////////////////////
	// Private methods, rarely used
	bool GetProfileKeyNamesBySection(const String& m_cfgFileName, 
		const String& wsSectionName, 
		std::vector<String>& arrKeyNames);

	void InvokeNewLoader(const String& wsCategoryName);
	void RemoveLoader(const String& wsCategoryName);

	//////////////////////////////////////////////////////////////////////////
	// Private fields, for really private member variables
	ComponentCategoryMap m_mapComponentCategories;
	ComponentLoaderThreadPool m_loaderThreadPool;
	String m_cfgFileName;
	ObjectModel* m_system;
};